% 下面是层次关系3次，神经网络节点2个，神经网络迭代一次，计算函数
% 1. 定义网络结构（3层：输入层+隐藏层+输出层）
n_input = 2;    % 输入层节点数（2个特征）
n_hidden = 3;   % 隐藏层节点数（3个神经元）
n_output = 1;   % 输出层节点数（1个回归/二分类输出）
lr = 0.1;       % 学习率

% 2. 初始化权重和偏置（随机初始化，避免全0）
W1 = randn(n_hidden, n_input) * 0.1;  % 隐藏层权重：3×2矩阵（隐藏层节点数×输入层节点数）
b1 = randn(n_hidden, 1) * 0.1;        % 隐藏层偏置：3×1向量（每个隐藏节点1个偏置）
W2 = randn(n_output, n_hidden) * 0.1; % 输出层权重：1×3矩阵（输出层节点数×隐藏层节点数）
b2 = randn(n_output, 1) * 0.1;        % 输出层偏置：1×1向量（每个输出节点1个偏置）

% 3. 准备输入数据和真实标签（4个样本，异或问题为例）
x = [0 0; 0 1; 1 0; 1 1];  % 输入数据：4×2矩阵（4个样本，每个样本2个特征）
y = [0; 1; 1; 0];           % 真实标签：4×1向量（每个样本1个标签，异或结果）

% 4. 前向传播（计算各层输出）
a0 = x;                                  % 输入层激活值：4×2（样本×特征）
z1 = W1 * a0' + b1;                      % 隐藏层加权和：3×4（隐藏节点×样本，a0'转置为2×4）
a1 = 1 ./ (1 + exp(-z1));                % 隐藏层激活值（sigmoid函数）：3×4
z2 = W2 * a1 + b2;                       % 输出层加权和：1×4（输出节点×样本）
a2 = 1 ./ (1 + exp(-z2));                % 输出层激活值（预测结果）：1×4

% 5. 计算损失（均方误差MSE）
loss = 0.5 * sum((a2 - y').^2);          % 标量：所有样本的平均损失（简化为求和）

% 6. 反向传播（计算误差和梯度）—— 仅修正这一行！
delta2 = (a2 - y') .* (a2 .* (1 - a2));  % 输出层误差：1×4（用输出层a2算导数，维度匹配）
delta1 = (W2' * delta2) .* (a1 .* (1 - a1)); % 隐藏层误差：3×4（用隐藏层a1算导数，正确）

% 7. 计算权重和偏置的梯度（基于4个样本的平均梯度）
dW2 = delta2 * a1' / size(x, 1);         % 输出层权重梯度：1×3（误差×隐藏层激活值，样本数归一化）
db2 = sum(delta2, 2) / size(x, 1);       % 输出层偏置梯度：1×1（误差求和，样本数归一化）
dW1 = delta1 * a0 / size(x, 1);          % 隐藏层权重梯度：3×2（误差×输入层激活值，样本数归一化）
db1 = sum(delta1, 2) / size(x, 1);       % 隐藏层偏置梯度：3×1（误差求和，样本数归一化）

% 8. 迭代1次：更新权重和偏置（梯度下降）
W2 = W2 - lr * dW2;
b2 = b2 - lr * db2;
W1 = W1 - lr * dW1;
b1 = b1 - lr * db1;

% 9. 输出迭代1次后的关键结果
fprintf('迭代1次后的损失：%.4f\n', loss);
fprintf('迭代1次后的输出层预测值：\n');
disp(a2');  % 转置为4×1，与标签y维度一致

